﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using RankDemo.WebApi.Dtos;
using RankDemo.WebApi.Entities;
using RankDemo.WebApi.Extensions;
using RankDemo.WebApi.Services;

namespace RankDemo.WebApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class LeaderboardController : ControllerBase
    {
        private readonly ICustomerService _customerService;
        private readonly IMemoryCache _memoryCache;

        public LeaderboardController(
            ICustomerService customerService,
            IMemoryCache memoryCache)
        {
            _customerService = customerService;
            _memoryCache = memoryCache;
        }

        [HttpGet]
        public List<LeaderboardDto> GetCustomersByRank(long start = default, long end = long.MaxValue)
        {
            if (start <= 0 || end <= 0)
            {
                throw new ArgumentException("Both the start value and the end value need to be greater than 0");
            }

            if (start >= end)
            {
                throw new ArgumentException("The start value needs to be less than the end value");
            }

            var leaderboardDtos = GetLeaderboardDtos();
            return leaderboardDtos.Where(l => l.Rank >= start && l.Rank <= end).ToList();
        }

        [HttpGet("{customerid}")]
        public List<LeaderboardDto> GetCustomersByCustomerId(long customerId, int high, int low)
        {
            var customer = _customerService.GetCustomer(customerId);
            if (customer == null)
            {
                throw new EntityNotFoundException(typeof(Customer), customerId);
            }

            if (customer.IsDefaultScoreValue())
            {
                throw new Exception("The customer is not on the leaderboard");
            }

            var leaderboardDtos = GetLeaderboardDtos();
            var leaderboardDto = leaderboardDtos.First(l => l.CustomerId == customer.CustomerId);

            var forwardRank = leaderboardDto.Rank - high;
            var backRank = leaderboardDto.Rank + low;

            return leaderboardDtos.Where(l => l.Rank >= forwardRank && l.Rank <= backRank).ToList();
        }

        private List<LeaderboardDto> GetLeaderboardDtos()
        {
            var leaderboardDtos = _memoryCache.Get<List<LeaderboardDto>>("leaderboard");
            return leaderboardDtos;
        }
    }
}